﻿namespace KeRui.Upload
{
    using System;
    using System.ComponentModel;
    using System.IO;
    using System.Runtime.InteropServices;

    internal class FileUtils
    {
        [DllImport("kernel32", CharSet=CharSet.Unicode, SetLastError=true)]
        private static extern int CreateFile(string filename, uint desiredAccess, uint shareMode, uint attributes, uint creationDisposition, uint flagsAndAttributes, uint templateFile);
        public static FileStream CreateFileStream(string inPath, FileMode inMode, FileAccess inAccess)
        {
            int num = inPath.LastIndexOf(':');
            if ((num > 2) && (num > inPath.LastIndexOf('\\')))
            {
                return MakeFileStream(inPath, inMode, inAccess);
            }
            return new FileStream(inPath, inMode, inAccess, FileShare.Read);
        }

        public static FileStream MakeFileStream(string inPath, FileMode inMode, FileAccess inAccess)
        {
            uint num;
            if (inAccess == FileAccess.Read)
            {
                num = 0x80000000;
            }
            else if (inAccess == FileAccess.Write)
            {
                num = 0x40000000;
            }
            else
            {
                num = 0xc0000000;
            }
            int num2 = CreateFile(inPath, num, 1, 0, (uint) inMode, 0x80, 0);
            if (num2 == -1)
            {
                int error = Marshal.GetLastWin32Error();
                switch (error)
                {
                    case 2:
                        throw new FileNotFoundException("File stream not found.", inPath);

                    case 0x7b:
                        throw new IOException("Unable to create named stream. Check that volume is NTFS formatted.");
                }
                throw new Win32Exception(error);
            }
            return new FileStream(new IntPtr(num2), FileAccess.Write, true);
        }

        public static byte[] ReadDataFromFile(string inPath)
        {
            FileStream stream = CreateFileStream(inPath, FileMode.Open, FileAccess.Read);
            byte[] buffer = new byte[stream.Length];
            int num = stream.Read(buffer, 0, buffer.Length);
            stream.Close();
            if (num != buffer.Length)
            {
                throw new IOException("Could not read all data from file.");
            }
            return buffer;
        }

        public static byte[] ReadDataFromStream(Stream inStream)
        {
            byte[] buffer = new byte[inStream.Length];
            if (inStream.Read(buffer, 0, buffer.Length) != buffer.Length)
            {
                throw new IOException("Could not read all data from stream.");
            }
            return buffer;
        }

        public static void StreamToStream(Stream inSrc, Stream inDst)
        {
            StreamToStream(inSrc, 0L, inDst, 0L, inSrc.Length - inSrc.Position, 0x10000);
        }

        public static void StreamToStream(Stream inSrc, long inSrcPos, Stream inDst, long inDstPos, long inLen, int inChunk)
        {
            byte[] buffer = new byte[inChunk];
            while (inLen > 0L)
            {
                if (inLen < inChunk)
                {
                    inChunk = (int) inLen;
                }
                inSrc.Read(buffer, 0, inChunk);
                inDst.Write(buffer, 0, inChunk);
                inLen -= inChunk;
            }
        }

        public static void WriteDataToFile(string inPath, bool inOverwrite, Stream inSource)
        {
            FileMode inMode = inOverwrite ? FileMode.Create : FileMode.CreateNew;
            FileStream inDst = CreateFileStream(inPath, inMode, FileAccess.Write);
            long position = inSource.Position;
            inSource.Position = 0L;
            StreamToStream(inSource, inDst);
            inSource.Position = position;
            inDst.Close();
        }

        public static void WriteDataToFile(string inPath, bool inOverwrite, byte[] inSource, int inStart, int inLength)
        {
            MemoryStream stream = new MemoryStream(inSource, inStart, inLength, false, false);
            WriteDataToFile(inPath, inOverwrite, stream);
            stream.Close();
        }
    }
}

